using UnityEditor;
using UnityEngine;

namespace DanMuHelper.Editor
{
    [InitializeOnLoad]
    internal static partial class CodeGenerator
    {
        static CodeGenerator()
        {
            EditorApplication.update -= EditorUpdate;
            if (EditorApplication.isPlayingOrWillChangePlaymode)
            {
                return;
            }
            if (EditorApplication.isCompiling || EditorApplication.isUpdating)
            {
                EditorApplication.update += EditorUpdate;
                return;
            }
        }

        private static void EditorUpdate()
        {
            if (EditorApplication.isCompiling || EditorApplication.isUpdating)
            {
                return;
            }
            EditorApplication.update -= EditorUpdate;

            GenerateTagAndLayerNames();
        }

        internal static void StartOrScheduleAutoRegenerate()
        {
            EditorApplication.update -= EditorUpdate;
            if (EditorApplication.isPlayingOrWillChangePlaymode)
            {
                Debug.Log("Playing or will change playmode, skip auto regenerate.");
                return;
            }
            if (EditorApplication.isCompiling || EditorApplication.isUpdating)
            {
                Debug.Log("Compiling or updating, schedule auto regenerate.");
                EditorApplication.update += EditorUpdate;
                return;
            }
            GenerateTagAndLayerNames();
        }

        /// <summary>
        /// 将字符串转换为C#标识符, 例如将"2D Object"转换为"_2DObject", 如果是关键字, 则在前面加上"@"
        /// </summary>
        private static string EnsureCSharpIdentifier(string name)
        {
            if (string.IsNullOrWhiteSpace(name))
            {
                return null;
            }

            if (name[0] >= '0' && name[0] <= '9')
            {
                name = "_" + name;
            }
            name = name.Replace(" ", "_");
            // if keyword, add @
            if (System.Array.IndexOf(_csharpKeywords, name) >= 0)
            {
                name = "@" + name;
            }
            // if not valid identifier, return null
            if (!System.CodeDom.Compiler.CodeGenerator.IsValidLanguageIndependentIdentifier(name))
            {
                UnityEngine.Debug.LogErrorFormat("Invalid identifier: {0}", name);
                return null;
            }
            return name;
        }

        /// <summary>
        /// C#关键字, 来自 https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/, 不能用作标识符, 代码生成时需要特殊处理
        /// </summary>
        private static readonly string[] _csharpKeywords = new string[]
        {
            "abstract",
            "as",
            "base",
            "bool",
            "break",
            "byte",
            "case",
            "catch",
            "char",
            "checked",
            "class",
            "const",
            "continue",
            "decimal",
            "default",
            "delegate",
            "do",
            "double",
            "else",
            "enum",
            "event",
            "explicit",
            "extern",
            "false",
            "finally",
            "fixed",
            "float",
            "for",
            "foreach",
            "goto",
            "if",
            "implicit",
            "in",
            "int",
            "interface",
            "internal",
            "is",
            "lock",
            "long",
            "namespace",
            "new",
            "null",
            "object",
            "operator",
            "out",
            "override",
            "params",
            "private",
            "protected",
            "public",
            "readonly",
            "ref",
            "return",
            "sbyte",
            "sealed",
            "short",
            "sizeof",
            "stackalloc",
            "static",
            "string",
            "struct",
            "switch",
            "this",
            "throw",
            "true",
            "try",
            "typeof",
            "uint",
            "ulong",
            "unchecked",
            "unsafe",
            "ushort",
            "using",
            "virtual",
            "void",
            "volatile",
            "while"
        };
    }
}
